/*
	FileName : BSP_spi.c
	Description :
		
		
	Created on 2013.10.14 by ZZP.
	
	Revision History:
		2018/9/30: H7. 
		For wifi-module ATWINC1500, spi FREQ=96/2=48MHz = max(48M)
*/
#include "stm32h7xx_hal.h"
#include "bsp.h"

SPI_HandleTypeDef hspix;
DMA_HandleTypeDef hdma_spix_tx;
DMA_HandleTypeDef hdma_spix_rx;

///osSemaphoreId	osSem_SPIx;

__IO uint8_t SpiReady = 1;



///////////////////////////////////////////////////////////////////////////////////////
///						Global function realizations
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///						Global function realizations
///////////////////////////////////////////////////////////////////////////////////////
uint8_t BSP_SPIx_ReadWrite(uint8_t *TxBuf, uint8_t *RxBuf, uint16_t len)
{
	///uint32_t err = 0;
		
	/*err = osSemaphoreWait(osSem_SPIx, 500u);
	if (err)
		return (err & 0xff);*/
	
	SpiReady = 0;
	if(HAL_SPI_TransmitReceive_DMA(&hspix, (uint8_t*)TxBuf, (uint8_t *)RxBuf, len) != HAL_OK)
	{
		/* Transfer error in transmission process */
		///Error_Handler();
		return 0xff;
	}
	else
		return 0;
}


uint8_t BSP_SPIx_GetStatus(void)
{
	return (SpiReady == 1);
}

void BSP_SPIx_EnableEXTI(void)
{
	HAL_NVIC_EnableIRQ(SPIx_EXTI_IRQn);
}

void BSP_SPIx_DisableEXTI(void)
{
	HAL_NVIC_DisableIRQ(SPIx_EXTI_IRQn);
}


void BSP_SPIx_Init(void)
{
	///osSemaphoreDef(SEM);
	///osSem_SPIx = osSemaphoreCreate(osSemaphore(SEM), 1);
	SpiReady = 1;
	
	/* SPI2 parameter configuration*/
	hspix.Instance = SPIx;
	hspix.Init.Mode = SPI_MODE_MASTER;
	hspix.Init.Direction = SPI_DIRECTION_2LINES;
	hspix.Init.DataSize = SPI_DATASIZE_8BIT;
	hspix.Init.CLKPolarity = SPI_POLARITY_LOW;
	hspix.Init.CLKPhase = SPI_PHASE_1EDGE;
	hspix.Init.NSS = SPI_NSS_SOFT;
	hspix.Init.BaudRatePrescaler = SPI_CLK_DIV;
	hspix.Init.FirstBit = SPI_FIRSTBIT_MSB;
	hspix.Init.TIMode = SPI_TIMODE_DISABLE;
	hspix.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
	hspix.Init.CRCPolynomial = 7;
	hspix.Init.CRCLength = SPI_CRC_LENGTH_8BIT;
	hspix.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
	hspix.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
	hspix.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
	hspix.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
	hspix.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
	hspix.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
	hspix.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
	hspix.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
	hspix.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
	hspix.Init.IOSwap = SPI_IO_SWAP_DISABLE;
	if (HAL_SPI_Init(&hspix) != HAL_OK)
	{
		///_Error_Handler(__FILE__, __LINE__);
	}
}

void BSP_SPIx_DeInit(void)
{
	if(HAL_SPI_DeInit(&hspix) != HAL_OK)
	{
		/* Initialization Error */
		///Error_Handler();
	}
	SpiReady = 1;
}


void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct;
	
  if(hspi->Instance==SPIx)
  {
    /* Peripheral clock enable */
    SPIx_CLK_GPIO_CLK_ENABLE();
    SPIx_MISO_GPIO_CLK_ENABEL();
    SPIx_MOSI_GPIO_CLK_ENABEL();
    SPIx_NSS_GPIO_CLK_ENABEL();
    SPIx_IRQ_GPIO_CLK_ENABEL();
	///enable SPIx clock
    SPIx_CLK_ENABLE();
	///enable SPI DMA clock
	SPIx_DMA_CLK_ENABLE();
  
	///CLK PIN
	GPIO_InitStruct.Pin = SPIx_CLK_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = SPIx_CLK_AF;
    HAL_GPIO_Init(SPIx_CLK_GPIO_PORT, &GPIO_InitStruct);
	///MISO PIN
	GPIO_InitStruct.Pin = SPIx_MISO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = SPIx_MISO_AF;
    HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct);
	///MOSI PIN
	GPIO_InitStruct.Pin = SPIx_MOSI_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = SPIx_MOSI_AF;
    HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct);
	///NSS PIN
	/*GPIO_InitStruct.Pin = SPIx_NSS_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = SPIx_NSS_AF;
    HAL_GPIO_Init(SPIx_NSS_GPIO_PORT, &GPIO_InitStruct);*/
	///IRQ PIN
	GPIO_InitStruct.Pin = SPIx_IRQ_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;///GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(SPIx_IRQ_GPIO_PORT, &GPIO_InitStruct);
	
	/* Enable and set EXTI lines 3 Interrupt to the lowest priority */
	HAL_NVIC_SetPriority(SPIx_EXTI_IRQn, SPIx_EXTI_INT_PRIO, 0);
	HAL_NVIC_EnableIRQ(SPIx_EXTI_IRQn);

    /* SPIx DMA Init */
    /* SPIx_TX Init */
    hdma_spix_tx.Instance = SPIx_DMA_TX_STREAM;
    hdma_spix_tx.Init.Request = SPIx_DMA_TX_CHANNEL;
    hdma_spix_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spix_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spix_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spix_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spix_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spix_tx.Init.Mode = DMA_NORMAL;
    hdma_spix_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spix_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
	hdma_spix_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
	hdma_spix_tx.Init.MemBurst = DMA_MBURST_SINGLE;
	hdma_spix_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_spix_tx) != HAL_OK)
    {
      ///_Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(hspi,hdmatx,hdma_spix_tx);

    /* SPI2_RX Init */
    hdma_spix_rx.Instance = SPIx_DMA_RX_STREAM;
    hdma_spix_rx.Init.Request = SPIx_DMA_RX_CHANNEL;
    hdma_spix_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spix_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spix_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spix_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spix_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spix_rx.Init.Mode = DMA_NORMAL;
    hdma_spix_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spix_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
	hdma_spix_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
	hdma_spix_rx.Init.MemBurst = DMA_MBURST_SINGLE;
	hdma_spix_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
    if (HAL_DMA_Init(&hdma_spix_rx) != HAL_OK)
    {
      ///_Error_Handler(__FILE__, __LINE__);
    }

    __HAL_LINKDMA(hspi,hdmarx,hdma_spix_rx);
	
	
	/* NVIC configuration for DMA transfer complete interrupt (SPI2_TX) */
    HAL_NVIC_SetPriority(SPIx_DMA_TX_IRQn, SPI2_DMA_INT_PRIO, 0);
    HAL_NVIC_EnableIRQ(SPIx_DMA_TX_IRQn);
    
    /* NVIC configuration for DMA transfer complete interrupt (SPI2_RX) */
    HAL_NVIC_SetPriority(SPIx_DMA_RX_IRQn, SPI2_DMA_INT_PRIO, 0);
    HAL_NVIC_EnableIRQ(SPIx_DMA_RX_IRQn);

    /* SPI2 interrupt Init */
    HAL_NVIC_SetPriority(SPIx_IRQn, SPIx_INT_PRIO, 0);
    HAL_NVIC_EnableIRQ(SPIx_IRQn);
  }
}

/**
  * @brief QSPI MSP De-Initialization
  *        This function frees the hardware resources used in this example:
  *          - Disable the Peripheral's clock
  *          - Revert GPIO, DMA and NVIC configuration to their default state
  * @param hqspi: QSPI handle pointer
  * @retval None
  */
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
{
  if(hspi->Instance==SPIx)
  {
    /* Peripheral clock disable */
    SPIx_CLK_DISABLE();
  
    HAL_GPIO_DeInit(SPIx_CLK_GPIO_PORT, SPIx_CLK_PIN);
    HAL_GPIO_DeInit(SPIx_MISO_GPIO_PORT, SPIx_MISO_PIN);
    HAL_GPIO_DeInit(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_PIN);

    /* SPI DMA DeInit */
    HAL_DMA_DeInit(hspi->hdmatx);
    HAL_DMA_DeInit(hspi->hdmarx);

    /* SPI2 interrupt DeInit */
    HAL_NVIC_DisableIRQ(SPIx_IRQn);
  }
}


void SPIx_IRQHandler(void)
{
  HAL_SPI_IRQHandler(&hspix);
}

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
	SpiReady = 1;
	///osSemaphoreRelease(osSem_SPIx);
}

void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
	///Error_Handler();
}


void SPIx_EXTI_IRQHandler(void)
{
	HAL_GPIO_EXTI_IRQHandler(SPIx_IRQ_PIN);
}
volatile uint16_t _ExtiCnt = 0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == SPIx_IRQ_PIN)
	{
		if (BSP_Info.Wifi_IrqCallBack != NULL)
			BSP_Info.Wifi_IrqCallBack(0, NULL);
		_ExtiCnt++;
	}
}

#if (BSP_SPI_2_ENABLE==DEF_ENABLED)
void SPIx_DMA_TX_IRQHandler(void)
{
	HAL_DMA_IRQHandler(hspix.hdmatx);
}


void SPIx_DMA_RX_IRQHandler(void)
{
	HAL_DMA_IRQHandler(hspix.hdmarx);
}
#endif


/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/


